﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace B121B {
    /// <summary>
    /// The collecion of vehicles
    /// </summary>
    public class VehicleCollection {
        /// <summary>
        /// Instantiates an vehicle collection
        /// </summary>
        /// <param name="sellers">The list of sellers</param>
        /// <param name="vehicles">The list of vehicles</param>
        public VehicleCollection() {
            Vehicles = new List<Vehicle>();
            Sellers = new List<Seller>();
        }

        #region Properties
        /// <summary>
        /// The vehicles
        /// </summary>
        private List<Vehicle> Vehicles { get; set; }

        /// <summary>
        /// The sellers
        /// </summary>
        public List<Seller> Sellers { get; private set; }

        /// <summary>
        /// Results from the previous search
        /// </summary>
        public List<Vehicle> PrevSearch { get; set; }
        #endregion

        /// <summary>
        /// Adds a vehicle to the collection
        /// </summary>
        /// <param name="vehicleToAdd">Vehicle to add</param>
        /// <returns>True if vehicle was added, false if vehicle already exists</returns>
        public bool AddVehicle(Vehicle vehicleToAdd) {
            if (Vehicles.Contains(vehicleToAdd)) { // Check if vehicle already exists
                return false;
            } else {
                Vehicles.Add(vehicleToAdd);
                return true;
            }
        }

        /// <summary>
        /// Get the vehicles in the collection
        /// </summary>
        /// <returns>The vehicles</returns>
        public List<Vehicle> GetVehicles() {
            return Vehicles;
        }

        /// <summary>
        /// Returns the list to search from
        /// </summary>
        /// <param name="contPrevSearch">Continue from previous search</param>
        /// <returns>The list to search from</returns>
        private List<Vehicle> SearchList(bool contPrevSearch) {
            List<Vehicle> retVehicles;
            if (contPrevSearch) {
                retVehicles = PrevSearch;
            } else {
                retVehicles = Vehicles;
            }
            return retVehicles;
        }

        /// <summary>
        /// Continue the previous search
        /// </summary>
        public void FillPrevSearchForAdvancedSearch() {
            PrevSearch = Vehicles;
        }

        /// <summary>
        /// Resets the previous search
        /// </summary>
        public void ResetSearch() {
            PrevSearch = new List<Vehicle>(Vehicles);
        }

        #region Search 1
        // We use lamba expressions only here, just to show you we can
        /// <summary>
        /// Finds all cars of a specific brand
        /// </summary>
        /// <param name="brand">Brand to find</param>
        /// <param name="contPrevSearch">Continue from previus search?</param>
        /// <returns>The cars of the specified brand</returns>
        public List<Vehicle> FindBrand(string brand, bool contPrevSearch) {
            List<Vehicle> retVehicles = SearchList(contPrevSearch);
            PrevSearch = (retVehicles.Where(v => v.Brand == brand).OrderBy(v => v.Price)).ToList();
            return PrevSearch;
        }

        /// <summary>
        /// Finds all cars of a specified model
        /// </summary>
        /// <param name="model">Model to find</param>
        /// <param name="contPrevSearch">Continue from previus search?</param>
        /// <returns>The cars of the specified model</returns>
        public List<Vehicle> FindModel(string model, bool contPrevSearch) {
            List<Vehicle> retVehicles = SearchList(contPrevSearch);
            PrevSearch = (retVehicles.Where(v => v.Model == model).OrderBy(v => v.Price)).ToList();
            return PrevSearch;
        }
        #endregion

        #region Search 2
        /// <summary>
        /// Finds the vehicle for sale in a selected area
        /// </summary>
        /// <param name="zip">The area to search in</param>
        /// <param name="contPrevSearch">Continue from previous search</param>
        /// <returns>The vehicles for sale in the selected area</returns>
        public List<Vehicle> ForSaleInZip(string zip, bool contPrevSearch) {
            List<Vehicle> retVehicles = SearchList(contPrevSearch);
            PrevSearch = (from v in retVehicles
                          where v.Seller.ZipCode == zip
                          orderby v.Price
                          select v).ToList();
            return PrevSearch;
        }
        #endregion

        #region Search 3
        /// <summary>
        /// Search assignment 3
        /// Finds the vehicles (with a loading capacity) with a minimum loadcap
        /// </summary>
        /// <param name="minLoadCap">The minimum loadcap</param>
        /// <param name="contPrevSearch">Continue from previous search</param>
        /// <returns>The vehicles with the selected minimum loadcap</returns>
        public List<Vehicle> MinLoadCap(int minLoadCap, bool contPrevSearch) {
            List<Vehicle> retVehicles = SearchList(contPrevSearch);

            List<Vehicle> trucks = (from v in retVehicles
                                    where v.VehicleType == VehicleTypes.Truck
                                    let truck = v as Truck
                                    where truck.LoadCapacity >= minLoadCap
                                    orderby truck.Weight
                                    select truck as Vehicle).ToList();
            List<Vehicle> vans = (from v in retVehicles
                                  where v.VehicleType == VehicleTypes.Van
                                  let van = v as Van
                                  where van.LoadCapacity >= minLoadCap
                                  orderby van.LoadCapacity
                                  select van as Vehicle).ToList();

            PrevSearch = trucks.Concat(vans).ToList();
            // husk at sortere
            return PrevSearch;
        }
        #endregion

        #region Search 4
        public List<Vehicle> FindLicenseBiggerThan(DriversLicense license, bool contPrevSearch) {
            List<Vehicle> retVehicles = SearchList(contPrevSearch);

            PrevSearch = (from v in retVehicles
                          where v is IRequireBigLicense
                          let n = v as IRequireBigLicense
                          where n.License >= license
                          orderby (n as Vehicle).Price
                          select (Vehicle)n).ToList();
            return retVehicles;
        }

        public List<Vehicle> FindPriceBelowOrEqualTo(int price, bool contPrevSearch) {
            List<Vehicle> retVehicles = SearchList(contPrevSearch);
            PrevSearch = (from v in retVehicles
                          where v.Price <= price
                          orderby v.Price
                          select v).ToList();
            return retVehicles;
        }
        #endregion
    }
}
